package org.bees.cms.core.clause;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Transient;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.bees.cms.common.Enumerable;
import org.bees.cms.core.Specific;

@Entity
public class Calculation extends Clause implements Specific<String> {
	private static final long serialVersionUID = -7136102918980338529L;

	private Gamma gamma;
	private String[] properties;
	private String[] parameters;

	@Override
	public String toSQL(Adapter adapter, Class<?> mapper, String alias) throws Exception {
		return gamma.toSQL(adapter, mapper, alias, properties, parameters);
	}

	public static enum Gamma implements Enumerable {
		AVG("求均值") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "AVG(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		SUM("求和") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "SUM(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		COUNT("统计") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "COUNT(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		FIRST("取第一个") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "FIRST(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		LAST("取最后一个") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "LAST(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		MAX("求最大值") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "MAX(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		MIN("求最小值") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "MIN(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		UCASE("变为大写") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "UCASE(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		LCASE("变为小写") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "LCASE(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		MID("提取字符") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "MID(" + adapter.adapt(mapper, properties[0], alias) + "," + parameters[0] + (parameters.length >= 3 ? "," + parameters[1] : "") + ")";
			}
		},
		LEN("求长度") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "LEN(" + adapter.adapt(mapper, properties[0], alias) + ")";
			}
		},
		ROUND("四舍五入") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "ROUND(" + adapter.adapt(mapper, properties[0], alias) + "," + parameters[0] + ")";
			}
		},
		NOW("当前日期") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "NOW()";
			}
		},
		FORMAT("格式化") {
			@Override
			public String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception {
				return "FORMAT(" + adapter.adapt(mapper, properties[0], alias) + ",'" + parameters[0] + "')";
			}
		};

		private String key;

		private Gamma(String key) {
			this.key = key;
		}

		public abstract String toSQL(Adapter adapter, Class<?> mapper, String alias, String[] properties, String[] parameters) throws Exception;

		@Override
		public String key() {
			return key;
		}

		@Override
		public String value() {
			return name();
		}

	}

	@Enumerated(EnumType.STRING)
	@Column(length = 10, nullable = false)
	public Gamma getGamma() {
		return gamma;
	}

	public void setGamma(Gamma gamma) {
		this.gamma = gamma;
	}

	@Transient
	@Column(name = "particular")
	public String[] getProperties() {
		return properties;
	}

	public void setProperties(String[] properties) {
		this.properties = properties;
	}

	@Transient
	@Column(name = "particular")
	public String[] getParameters() {
		return parameters;
	}

	public void setParameters(String[] parameters) {
		this.parameters = parameters;
	}

	@Column(length = 200)
	@Override
	public String getParticular() throws Exception {
		JSONObject object = new JSONObject();

		JSONArray _properties = new JSONArray();
		for (int i = 0; properties != null && i < properties.length; i++) {
			JSONObject property = new JSONObject();
			property.accumulate("property", properties[i]);
			_properties.add(property);
		}
		object.accumulate("properties", _properties);

		JSONArray _parameters = new JSONArray();
		for (int i = 0; parameters != null && i < parameters.length; i++) {
			JSONObject parameter = new JSONObject();
			parameter.accumulate("parameter", parameters[i]);
			_parameters.add(parameter);
		}
		object.accumulate("parameters", _parameters);

		return object.toString();
	}

	@Override
	public void setParticular(String particular) throws Exception {
		JSONObject object = JSONObject.fromObject(particular);

		JSONArray _properties = object.getJSONArray("properties");
		properties = new String[_properties.size()];
		for (int i = 0; i < _properties.size(); i++) {
			properties[i] = _properties.getJSONObject(i).getString("property");
		}

		JSONArray _parameters = object.getJSONArray("parameters");
		parameters = new String[_parameters.size()];
		for (int i = 0; i < _parameters.size(); i++) {
			parameters[i] = _parameters.getJSONObject(i).getString("parameter");
		}
	}

}
